#! /usr/bin/python3
# -*- coding: UTF-8 -*-

if __name__ == "__main__":
	raise Exception("不支持从这里调用")

__version__ = "1.0"
__all__ = ["MouseChshAuthorizationAnnotition"]

from com.mousechsh.business.lib.model.MouseChshLoginModel import MouseChshLoginModel
from com.mousechsh.common.code.MouseChshAnnotation import mousechsh_annotation
from com.mousechsh.common.data.MouseChshDao import MouseChshDao
from com.mousechsh.common.data.json.MouseChshJson import mousechsh_json_from_json, mousechsh_json_to_json
from com.mousechsh.common.io.cache.MouseChshRedisCache import MouseChshRedisCache
from com.mousechsh.common.io.db.MouseChshPostgresql import MouseChshPostgresql
from com.mousechsh.common.log.MouseChshLog import mousechsh_logging_data
from com.mousechsh.common.log.MouseChshLog import mousechsh_logging_exception
from com.mousechsh.common.middle.auth.MouseChshJwt import mousechsh_jwt_decode_string
from com.mousechsh.common.middle.conf.MouseChshConfiguration import mousechsh_configuration_get
from com.mousechsh.common.middle.http.MouseChshHttpClient import MouseChshHttpClient
from com.mousechsh.common.middle.http.MouseChshHttpHeader import mousechsh_http_header_authorization
from com.mousechsh.common.middle.rest_api.MouseChshRestApi import mousechsh_rest_api_response
from com.mousechsh.common.util.MouseChshDateTime import MouseChshDateTime


@mousechsh_annotation
def MouseChshAuthorizationAnnotition(func):
	def MouseChshAuthorizationAnnotitionWrapper(url, request, response, *argsArr, **argsDict):
		auth = mousechsh_http_header_authorization(request)
		if auth['type'] == 'Bearer':
			jwt_check = (mousechsh_configuration_get('token.check.mode', 'jwt-first') == 'jwt-first')
			if jwt_check:
				obj = mousechsh_jwt_decode_string(auth['origin'], auth['data']['App'])
			else:
				obj = {'verify': False}
			if obj['verify']:
				auth = dict(auth, **obj)
				mousechsh_logging_data(auth, '令牌验证：通过JWT验证成功')
			else:
				flag = False
				try:
					loginMode = mousechsh_configuration_get('login.mode', 'each')

					cache = MouseChshRedisCache()
					cache.connect()
					if loginMode == 'each':
						cacheobj = cache.get('MousechshLogin:Id=' + auth['data']['Id'])
					elif loginMode == 'user':
						cacheobj = cache.get('MousechshLogin:User=' + auth['data']['User'])
					elif loginMode == 'user-app':
						cacheobj = cache.get(
							'MousechshLogin:User=' + auth['data']['User'] + ',App=' + auth['data']['App']
						)
					cache.close()

					if cacheobj is None:
						flag = True
					cacheobj = mousechsh_json_from_json(cacheobj)
					if cacheobj is None:
						flag = True
					elif cacheobj['Id'] != auth['data']['Id']:
						flag = True

					if not flag:
						auth['verify'] = True
						mousechsh_logging_data(auth, '令牌验证：通过缓存验证验证成功')
				except Exception as ex:
					mousechsh_logging_exception(ex, '访问缓存验证TOKEN时遇到错误：')
					mousechsh_rest_api_response(-1, None, response)
					return
				if flag:
					db = MouseChshPostgresql()
					db.connect()
					data = db.get(
						'''
					   SELECT
						   "C_Id",
						   "C_Code",
						   "L_User_Id" AS "C_User_Id",
						   "L_Domain_Id" AS "C_Domain_Id",
						   "L_App_Id" AS "C_App_Id",
						   "C_LoginTime",
						   "C_Alive",
						   "C_ExpTime"
					   FROM "A_Application"."T_Login"
					   WHERE "C_Id" = %(id)s
					   AND "C_ExpTime" >= %(exp)s
										   ''', {
							'id': auth['data']['Id'],
							'exp': MouseChshDateTime().to_timestamp()
						}
					)
					db.close()
					dao = MouseChshDao()
					dao.set_model(MouseChshLoginModel)
					logins = dao.parse(data)
					if len(logins) <= 0:
						mousechsh_logging_data(auth, '令牌验证：通过JWT、缓存、数据库方式都验证失败！')
						mousechsh_rest_api_response(-1, None, response)
						return
					login = logins[0]
					auth['verify'] = True

					cache = MouseChshRedisCache()
					cache.connect()
					if loginMode == 'each':
						cache.set(
							'MousechshLogin:Id=' + login.get('Id'), mousechsh_json_to_json(login),
							MouseChshDateTime().from_string(
								login.get('ExpTime')
							).to_timestamp() - MouseChshDateTime().to_timestamp()
						)
					elif loginMode == 'user':
						cache.set(
							'MousechshLogin:User=' + login.get('User'), mousechsh_json_to_json(login),
							MouseChshDateTime().from_string(
								login.get('ExpTime')
							).to_timestamp() - MouseChshDateTime().to_timestamp()
						)
					elif loginMode == 'user-app':
						cache.set(
							'MousechshLogin:User=' + login.get('User') + ',App=' + login.get('App'),
							mousechsh_json_to_json(login), MouseChshDateTime().from_string(
								login.get('ExpTime')
							).to_timestamp() - MouseChshDateTime().to_timestamp()
						)
					cache.close()
					mousechsh_logging_data(auth, '令牌验证：通过数据库验证成功')
		func(url, request, response, auth=auth, *argsArr, **argsDict)

	return MouseChshAuthorizationAnnotitionWrapper


@mousechsh_annotation
def MouseChshRemoteAuthorizationAnnotition(func):
	def MouseChshAuthorizationAnnotitionWrapper(url, request, response, *argsArr, **argsDict):
		auth = mousechsh_http_header_authorization(request)
		if auth['type'] == 'Bearer':
			jwt_check = (mousechsh_configuration_get('token.check.mode', 'jwt-first') == 'jwt-first')
			if jwt_check:
				obj = mousechsh_jwt_decode_string(auth['origin'], auth['data']['App'])
			else:
				obj = {'verify': False}
			if obj['verify']:
				auth = dict(auth, **obj)
				mousechsh_logging_data(auth, '令牌验证：通过JWT验证成功')
			else:
				conf = mousechsh_configuration_get('auth.mode', 'cache')
				if conf == 'cache':
					try:
						loginMode = mousechsh_configuration_get('login.mode', 'each')

						cache = MouseChshRedisCache()
						cache.set_host(mousechsh_configuration_get('redis.connection.host', '127.0.0.1'))
						cache.set_port(mousechsh_configuration_get('redis.connection.port', 6379))
						cache.connect()
						if loginMode == 'each':
							cacheobj = cache.get('MousechshLogin:Id=' + auth['data']['Id'])
						elif loginMode == 'user':
							cacheobj = cache.get('MousechshLogin:User=' + auth['data']['User'])
						elif loginMode == 'user-app':
							cacheobj = cache.get(
								'MousechshLogin:User=' + auth['data']['User'] + ',App=' + auth['data']['App']
							)
						cache.close()

						if cacheobj is None:
							mousechsh_logging_data(auth, '令牌验证：通过JWT、缓存方式都验证失败！')
							mousechsh_rest_api_response(-1, None, response)
							return
						cacheobj = mousechsh_json_from_json(cacheobj)
						if cacheobj is None:
							mousechsh_logging_data(auth, '令牌验证：通过JWT、缓存方式都验证失败！')
							mousechsh_rest_api_response(-1, None, response)
							return
						elif cacheobj['Id'] != auth['data']['Id']:
							mousechsh_logging_data(auth, '令牌验证：通过JWT、缓存方式都验证失败！')
							mousechsh_rest_api_response(-1, None, response)
							return
					except Exception as ex:
						mousechsh_logging_exception(ex, '访问缓存验证TOKEN时遇到错误：')
						mousechsh_rest_api_response(-1, None, response)
						return
					auth['verify'] = True
					mousechsh_logging_data(auth, '令牌验证：通过缓存验证验证成功')
				elif conf == 'remote':
					try:
						client = MouseChshHttpClient()
						client.set_host(mousechsh_configuration_get('auth.server.host', '127.0.0.1'))
						client.set_port(mousechsh_configuration_get('auth.server.port', 8000))
						client.set_method(mousechsh_configuration_get('auth.server.token.method', 'POST'))
						client.set_path(mousechsh_configuration_get('auth.server.token.path', '/check/token'))
						client.forgery_header()
						client.set_header(
							'Authorization', (auth['type'] + ' ' if auth['type'] else '') + auth['origin']
						)
						client.run()
						result = client.sync('')
						client.close()
						data = result.get_body()
						jobj = mousechsh_json_from_json(data)
						if jobj is None or not jobj['data']:
							mousechsh_logging_data(auth, '令牌验证：通过JWT、远程服务器方式都验证失败！')
							mousechsh_rest_api_response(-1, None, response)
							return
					except Exception as ex:
						mousechsh_logging_exception(ex, '访问远程服务器验证TOKEN时遇到错误：')
						mousechsh_rest_api_response(-1, None, response)
						return
					auth['verify'] = True
					mousechsh_logging_data(auth, '令牌验证：通过远程服务器验证成功')
		func(url, request, response, auth=auth, *argsArr, **argsDict)

	return MouseChshAuthorizationAnnotitionWrapper
